// Kony

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/PlayerController.h"
#include "GameplayTagContainer.h"
#include "BasePlayerController.generated.h"

class ITargetInterface;
class UInputMappingContext;
class UInputAction;
struct FInputActionValue;
class IEnemyInterface;
class UBaseInputConfig;
class UBaseAbilitySystemComponent;
class USplineComponent;
class UDamageTextComponent;
class UNiagaraSystem;
class ABaseMagicCircle;

//鼠标选中的目标对象状态枚举，区分是敌人 玩家还是物件等
enum class ETargetingStatus : uint8
{
	NotTargeting,
	TargetingEnemy,
	TargetingPlayer,
	TargetingNPC,
	TargetingObject,
};

/**
 * 玩家控制器类
 */
UCLASS()
class GASC_HUANLING_API ABasePlayerController : public APlayerController
{
	GENERATED_BODY()
public:
	ABasePlayerController();
	virtual void PlayerTick(float DeltaTime) override;
	//RPC 伤害显示函数 如果是服务端就服务端显示 如果是客户端就客户端显示
	UFUNCTION(Client, Reliable)
	void ShowDamageNumber(float DamageAmount, ACharacter* TargetCharacter, bool bBlockedHit, bool bCriticalHit);

	//显示/隐藏 魔法阵函数
	UFUNCTION(BlueprintCallable)
	void ShowMagicCircle(UMaterialInstance* DecalMaterial = nullptr, FGameplayTag SpellInputTag = FGameplayTag());
	UFUNCTION(BlueprintCallable)
	void HideMagicCircle();

protected:
	virtual void BeginPlay() override;
	virtual void SetupInputComponent() override;
	
private:
	UPROPERTY(EditAnywhere,  Category = "Input")
	TObjectPtr<UInputMappingContext> PlayerInputContext;

	UPROPERTY(EditAnywhere, Category = "Input")
	TObjectPtr<UInputAction> MoveAction;
	//强制攻击
	UPROPERTY(EditAnywhere, Category = "Input")
	TObjectPtr<UInputAction> ShiftAction;
	
	void Move(const FInputActionValue& InputActionValue);

	void ShiftPressed(){ bShiftKeyDown = true;};
	void ShiftReleased(){ bShiftKeyDown = false;};
	bool bShiftKeyDown = false;
	//鼠标选中函数
	void CursorTrace();
	//目标高亮相关参数
	// TScriptInterface<ITargetInterface> LastActor;
	// TScriptInterface<ITargetInterface> ThisActor;
	TObjectPtr<AActor> LastActor;
	TObjectPtr<AActor> ThisActor;
	//光标命中检测
	FHitResult CursorHit;
	static void HighlightActor(AActor* InActor); //显示高亮
	static void UnHighlightActor(AActor* InActor); //接触高亮
	//判断鼠标选中的目标函数
	ETargetingStatus DetermineTargetingStatus(AActor* InActor);
	//按键按下函数
	void AbilityInputTagPressed(FGameplayTag InputTag);
	//按键松开函数
	void AbilityInputTagReleased(FGameplayTag InputTag);
	//按键按住函数
	void AbilityInputTagHeld(FGameplayTag InputTag);
	
	UPROPERTY(EditDefaultsOnly, Category = "Input")
	TObjectPtr<UBaseInputConfig> InputConfig;

	//游戏能力组件指针 用于绑定玩家按键触发能力 避免重复类型转换
	UPROPERTY()
	TObjectPtr<UBaseAbilitySystemComponent> BaseAbilitySystemComponent;

	UBaseAbilitySystemComponent* GetASC();

	//左键点击目的地 保存向量 
	FVector CachedDestination;
	//用于判断 是长按还是短按
	float FollowTime = 0.f;
	//用于判断是否是长按
	float ShortPressThreshold = 0.5f;
	//用于判断是否在自动移动
	bool bAutoRunning = false;
	//用于判断当前鼠标是否瞄准了一个目标 枚举
	ETargetingStatus TargetingStatus = ETargetingStatus::NotTargeting;
	//用于设置自动移动的半径
	UPROPERTY(EditDefaultsOnly)
	float AutoRunAcceptanceRadius = 50.f;
	//样条组件变量
	UPROPERTY(VisibleAnywhere)
	TObjectPtr<USplineComponent> Spline;
	//点击粒子系统 - 点击移动地面 显示光标
	UPROPERTY(EditDefaultsOnly)
	TObjectPtr<UNiagaraSystem> ClickNiagaraSystem;
	
	//自动移动函数
	void AutoRun();
	
	// 8方向标准化函数：将任意方向向量标准化到8个固定方向
	FVector NormalizeTo8Directions(const FVector& Direction);

	//伤害显示组件变量
	UPROPERTY(EditDefaultsOnly)
	TSubclassOf<UDamageTextComponent> DamageTextComponentClass;

	//生成魔法阵类型
	UPROPERTY(EditDefaultsOnly)
	TSubclassOf<ABaseMagicCircle> MagicCircleClass;
	//魔法阵本身
	UPROPERTY()
	TObjectPtr<ABaseMagicCircle> MagicCircle;

	//法阵状态管理
	bool bMagicCircleActive = false;
	bool bMagicCircleJustCast = false;
	FGameplayTag CurrentSpellInputTag;

	//更新魔法阵位置
	void UpdateMagicCircleLocation();
};
